package com.coocaa.cirrus.common.base.util;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.log4j.Log4j2;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Objects;

/**
 * @author zen
 * @date 2020-10-15 11:17
 * @description
 */
@Log4j2
public class ClientIPUtil {

    public static String getClientIP(HttpServletRequest request) {
        String clientIP = "";
        try {
            clientIP = getIpAddr(request);
        } catch (Exception e) {
            log.error("获取客户端访问IP失败!");
            e.printStackTrace();
        }
        return clientIP;
    }


    /**
     * 获取当前网络ip
     *
     * @param request
     * @return
     */
    private static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("User-IP");
        String unknown = "unknown";
        String[] ipHeaders = {"X-Real-IP", "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP"};
        for (String ipHeader : ipHeaders) {
            if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader(ipHeader);
            } else {
                // header中获取的 ip 有时有多个的情况，取最末尾的一个
                if (ip.contains(",")) {
                    String[] ipArray = ip.split(",");
                    return StringUtils.trimAllWhitespace(ipArray[ipArray.length - 1]);
                }
                return StringUtils.trimAllWhitespace(ip);
            }
        }
        return request.getRemoteAddr();
    }

    /**
     * 专门通过X-Forwarded-For请求头获取客户端真实IP
     * 在网关代理环境下，X-Forwarded-For包含了原始客户端IP和所有经过的代理服务器IP
     * 格式为: client_ip, proxy1_ip, proxy2_ip, ...
     * 我们需要获取最左边的IP，即原始客户端IP
     *
     * @param request HTTP请求对象
     * @return 客户端真实IP
     */
    public static String getIpAddrByXForwardedFor(HttpServletRequest request) {
        if (request == null) {
            return "";
        }

        try {
            String xForwardedFor = request.getHeader("X-Forwarded-For");

            // 如果X-Forwarded-For为空，则尝试其他备用头信息
            if (StringUtils.isEmpty(xForwardedFor) || "unknown".equalsIgnoreCase(xForwardedFor)) {
                return getIpAddr(request);
            }

            // 处理X-Forwarded-For包含多个IP的情况，取第一个IP（客户端原始IP）
            if (xForwardedFor.contains(",")) {
                String[] ipArray = xForwardedFor.split(",");
                // 取第一个非空IP（最左边的IP是原始客户端IP）
                for (String ip : ipArray) {
                    ip = StringUtils.trimAllWhitespace(ip);
                    if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
                        return ip;
                    }
                }
            }

            // 单个IP情况，直接返回
            return StringUtils.trimAllWhitespace(xForwardedFor);

        } catch (Exception e) {
            log.error("通过X-Forwarded-For获取客户端IP失败", e);
            // 出错时回退到标准方法
            return getIpAddr(request);
        }
    }


    /**
     * 获取非本地/局域网IP地址
     * 如果IP是本地IP或局域网IP，则返回固定IP: 183.233.208.162
     * 否则按原逻辑返回客户端真实IP
     *
     * @param request HTTP请求对象
     * @return 非本地/局域网IP地址
     */
    public static String getNonLocalIpAddr(HttpServletRequest request) {
        String ip = getClientIP(request);
        // 判断是否为本地IP或局域网IP
        if (isLocalIp(request) ||
                ip.startsWith("10.") ||
                isPrivate172IP(ip) ||  // 使用精确的172私有IP判断方法
                ip.startsWith("192.168.") ||
                ip.startsWith("169.254.") ||
                ip.equals("0.0.0.0") ||
                ip.equals("::1") ||
                ip.startsWith("fc00::") ||
                ip.startsWith("fe80::")) {
            return "183.233.208.162";
        }
        return ip;
    }

    /**
     * 判断是否为172.16.0.0/12私有IP范围
     * 私有IP范围为: 172.16.0.0 - 172.31.255.255
     *
     * @param ip IP地址
     * @return 是否为172私有IP
     */
    private static boolean isPrivate172IP(String ip) {
        if (ip == null || !ip.startsWith("172.")) {
            return false;
        }

        try {
            // 提取第二个数字段
            String[] parts = ip.split("\\.");
            if (parts.length > 1) {
                int secondPart = Integer.parseInt(parts[1]);
                // 检查是否在16-31范围内
                return secondPart >= 16 && secondPart <= 31;
            }
        } catch (Exception e) {
            // 解析异常，不是有效的IP格式
            log.warn("解析IP地址异常: {}", ip, e);
        }

        return false;
    }

    public static String getIpAddr() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        if (null == request) {
            return "";
        }
        return getIpAddr(request);
    }


    public static boolean isLocalIp(HttpServletRequest request) {
        String ip = getClientIP(request);
        return ip.equals("127.0.0.1") || ip.equals("localhost") || ip.equals("0:0:0:0:0:0:0:1");
    }

}
